package lumis.util;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

import lumis.portal.dao.jdbc.ITransactionJdbc;
import lumis.portal.stability.StableMinor;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.util.log.ILogger;
import lumis.util.log.LoggerFactory;

/**
 * Database type
 *
 * @version $Revision: 13082 $ $Date: 2011-05-27 16:03:12 -0300 (Fri, 27 May 2011) $
 * @since 4.0.0
 */
@StableMinor(version = "6.0", sinceVersion = "4.0")
public enum DatabaseType
{
	ORACLE ("Oracle"),
	SQL_SERVER ("Microsoft SQL Server"),
	MY_SQL ("MySQL"),
	HYPERSONIC_SQL ("HypersonicSQL");
	
	private static ILogger logger = LoggerFactory.getLogger(DatabaseType.class);

	/**
	 * Stores the portal database type returned by {@link #getDatabaseType()}.
	 * @since 4.0.11
	 */
	private static DatabaseType portalDatabaseType;
	static
	{
		try
		{
			ITransactionJdbc transaction = (ITransactionJdbc)PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();
				portalDatabaseType = DatabaseType.getDatabaseType(transaction.getConnection());
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (Exception e)
		{
			logger.error("Error trying to identify portal's database type", e);
		}
	}
	
	private final String productName;

	DatabaseType(String productName)
	{
		this.productName = productName;
	}

	public String getProductName()
	{
		return productName;
	}
	
	/**
	 * Returns an instance of {@link DatabaseType} corresponding to the database the 
	 * given connection is connected to.
	 * @param connection the connection.
	 * @return the database type, never null.
	 * @throws SQLException if it was not possible to obtain the corresponding database type.
	 */
	public static DatabaseType getDatabaseType(Connection connection) throws SQLException
	{
		DatabaseMetaData databaseMetaData = connection.getMetaData();
		String databaseProduct = databaseMetaData.getDatabaseProductName();

		for (DatabaseType dbType: values())
		{
			if (dbType.getProductName().equals(databaseProduct))
				return dbType;
		}
		
		throw new SQLException("Unknown database product name: " + databaseProduct);
	}
	
	/**
	 * Returns an instance of {@link DatabaseType} corresponding to the database 
	 * the portal's default transaction accesses.
	 * @return the database type.
	 * @since 4.0.11
	 */
	public static DatabaseType getDatabaseType()
	{
		return portalDatabaseType;
	}
}
